package cmd

import (
	ckeadm "ckeadm/cmd/apis"
	ckeadmv1beta1 "ckeadm/cmd/apis/v1alpha1"
	"ckeadm/cmd/executor"
	"ckeadm/cmd/runner"
	"ckeadm/constants"
	"ckeadm/util"
	"fmt"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
	"os"
	"time"
)

func DeleteCommand() cli.Command {
	var deleteFlags = []cli.Flag {
		runner.ConfigPathFlag,
		runner.PrivateKey,
		runner.LogLevelFlag,
		runner.SureButtonFlag,
		runner.AddressFlag,
	}

	return cli.Command {
		Name:   "delete",
		Usage:  "Delete Cluster By Configuration",
		Action: clusterDeleteFromCli,
		Flags:  deleteFlags,
	}
}

// runKubeletStart executes kubelet start logic.
func runDelete(ctx *cli.Context) error {
	logrus.Infof("start delete cluster")
	config, err := runner.GetConfigFromFile(ctx.String("f"))
	if err != nil {
		return fmt.Errorf("error while get config from %s, err: %s", ctx.String("f"), err.Error())
	}
	logrus.SetLevel(logrus.Level(ctx.Int("v")))
	logrus.Debugf("configration get from %s, list here: \n%+v\n", ctx.String("f"), config)

	var privatekey string
	if privatekey, err = runner.GetPrivateKeyFromFile(ctx.String("private-key")); err != nil {
		return fmt.Errorf("error while get connection private key %s, err: %s", ctx.String("private-key"), err.Error())
	}

	// enter yes to continue
	var yes = "none"
	for !ctx.Bool("y") && yes != "Y" && yes != "n" {
		fmt.Print("Do you want to continue? [Y/n]")
		_, _ = fmt.Scanln(&yes)
	}
	if yes == "n" {
		logrus.Infof("you type [%s], so will not delete kubernetes.", yes)
		return nil
	}

	invFile, allFile, _ := GetAnsibleConfigPath(config)
	if err = WriteConfigFile(config, invFile, allFile); err != nil {
		return fmt.Errorf("error while write config: %s", err.Error())
	}
	logrus.Infof("deleted configration create at: %s, %s\n", invFile, allFile)

	var del = &ckeadm.AnsibleDockerPerms {
		ContainerName: fmt.Sprintf("%s-%s", constants.CkeDeployContainerName, config.ClusterName),
		ImageName:     ImageGetFromConfig(config),
		PrivateKey:    privatekey,
		InvFilePath:   invFile,
		AllFilePath:   allFile,
		ExecerPatch:   fmt.Sprintf("%s/%s", constants.CkeDeployDir, "delete.yml"),
	}
	mounts := append([]string {
		fmt.Sprintf("%s:%s", del.InvFilePath, constants.AnsibleConfig),
		fmt.Sprintf("%s:%s", del.AllFilePath, constants.AnsibleAllConfig),
	})
	_ = os.RemoveAll(fmt.Sprintf("%s/%s", constants.CkeadmLogCacheDir, config.ClusterName))
	return runner.AnsibleRunner(del.ContainerName, del.ImageName, del.ExecerPatch, false, del.PrivateKey, 0, mounts...)
}

func clusterDeleteFromCli(ctx *cli.Context) error {
	logrus.Infof("start delete cluster")
	path := ctx.String("f")
	config, err := runner.GetConfigFromFile(path)
	if err != nil {
		return fmt.Errorf("error while get config from %s, err: %s", ctx.String("f"), err.Error())
	}
	logrus.SetLevel(logrus.Level(ctx.Int("v")))
	logrus.Debugf("configration get from %s, list here: \n%+v\n", ctx.String("f"), config)

	var privatekey string
	if privatekey, err = runner.GetPrivateKeyFromFile(ctx.String("private-key")); err != nil {
		return fmt.Errorf("error while get connection private key %s, err: %s", ctx.String("private-key"), err.Error())
	}
	// enter yes to continue
	var yes = "none"
	for !ctx.Bool("y") && yes != "Y" && yes != "n" {
		fmt.Print("Do you want to continue? [Y/n]")
		fmt.Scanln(&yes)
	}
	if yes == "n" {
		logrus.Infof("you type [%s], so will not delete kubernetes.", yes)
		return nil
	}

	ckeComponents, ckeCluster, ckeNodes, err := runner.GetComponents(path)
	if err != nil {
		return fmt.Errorf("failed to get components: %s", err.Error())
	}

	address := ctx.String("address")
	logrus.Infof("address:%s", address)
	if address == "" {
		go func() {
			logrus.Error("failed:miss 'address' parameter")
		}()
		go func() {
			time.Sleep(time.Second)
			os.Exit(1)
		}()
		select {}
	}
	var watchConfig = &ckeadm.WatchConfig{ListenAddress: address, ListenPort: constants.WaitPort,
		LogCacheDir: constants.CkeadmLogCacheDir, CluserID: ckeCluster.ObjectMeta.Name, ConfigPath: path}
	keyFile, _ := runner.GetPrivateKeyFile(ctx.String("private-key"))


	//	保持向前兼容：如果没有定义组件，则调用ansible镜像脚本执行删除集群
	if ckeComponents == nil {
		invFile, allFile, _ := GetAnsibleConfigPath(config)
		if err = WriteConfigFile(config, invFile, allFile); err != nil {
			return fmt.Errorf("error while write config: %s", err.Error())
		}
		logrus.Infof("deleted configration create at: %s, %s\n", invFile, allFile)

		var del = &ckeadm.AnsibleDockerPerms {
			ContainerName: fmt.Sprintf("%s-%s", constants.CkeDeployContainerName, config.ClusterName),
			ImageName:     ImageGetFromConfig(config),
			PrivateKey:    privatekey,
			InvFilePath:   invFile,
			AllFilePath:   allFile,
			ExecerPatch:   fmt.Sprintf("%s/%s", constants.CkeDeployDir, "delete.yml"),
		}
		mounts := append([]string {
			fmt.Sprintf("%s:%s", del.InvFilePath, constants.AnsibleConfig),
			fmt.Sprintf("%s:%s", del.AllFilePath, constants.AnsibleAllConfig),
		})
		os.RemoveAll(fmt.Sprintf("%s/%s", constants.CkeadmLogCacheDir, config.ClusterName))
		return runner.AnsibleRunner(del.ContainerName, del.ImageName, del.ExecerPatch, false, del.PrivateKey, 0, mounts...)
	}

	_, ckecomponentsSorting := util.CheckAndSort(*ckeComponents)

	//	倒序排序的组件数组
	sortedCkeComponents := new([]ckeadmv1beta1.CkeComponent)
	l := len(ckecomponentsSorting)
	allCompNames := make([]string,0)
	for index := 0; index < l; index ++ {
		allCompNames = append(allCompNames,ckecomponentsSorting[l - index -1]...)
	}
	for _, comName := range allCompNames{
		for _, com := range *ckeComponents {
			if com.Name == comName {
				*sortedCkeComponents = append(*sortedCkeComponents,com)
				break
			}
		}
	}

	err = executor.DeleteComponent(sortedCkeComponents, ckeCluster, ckeNodes, keyFile, *watchConfig)
	if err != nil {
		logrus.Infof("failed to delete cluster by running component-delete-script. error=%s", err.Error())
	}

	invFile, allFile, _ := GetAnsibleConfigPath(config)
	if err = WriteConfigFile(config, invFile, allFile); err != nil {
		return fmt.Errorf("error while write config: %s", err.Error())
	}
	logrus.Infof("delete-cluster configuration created. invFilePath=%s allFilePath=%s", invFile, allFile)

	logrus.Infof("delete cluster by running ansible-container", invFile, allFile)

	var del = &ckeadm.AnsibleDockerPerms {
		ContainerName: fmt.Sprintf("%s-%s", constants.CkeDeployContainerName, config.ClusterName),
		ImageName:     ImageGetFromConfig(config),
		PrivateKey:    privatekey,
		InvFilePath:   invFile,
		AllFilePath:   allFile,
		ExecerPatch:   fmt.Sprintf("%s/%s", constants.CkeDeployDir, "delete.yml"),
	}
	mounts := append([]string {
		fmt.Sprintf("%s:%s", del.InvFilePath, constants.AnsibleConfig),
		fmt.Sprintf("%s:%s", del.AllFilePath, constants.AnsibleAllConfig),
	})
	_ = os.RemoveAll(fmt.Sprintf("%s/%s", constants.CkeadmLogCacheDir, config.ClusterName))
	return runner.AnsibleRunner(del.ContainerName, del.ImageName, del.ExecerPatch, false, del.PrivateKey, 0, mounts...)
}
